﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Shared.Method;
using Shared.Model;
using StationTestDll;

namespace ModemSystemNew
{
    public partial class WriteUint : UserControl
    {
        private Common _commonObj = null;

        private readonly string _serialPortName = string.Empty;
        private readonly string _serialPowerName = string.Empty;
        private readonly int _unitNumber = 0;
        private readonly string _stationIp = string.Empty;
        private string _log = string.Empty;

        public WriteUint(int unitNumber)
        {
            _unitNumber = unitNumber;

            string localIp = AppSetting.GetValue($"LocalIp{unitNumber}");
            int.TryParse(AppSetting.GetValue($"LocalPort{unitNumber}"), out int localPort);

            _serialPortName = AppSetting.GetValue($"ComName{unitNumber}");
            _serialPowerName = AppSetting.GetValue("PowerSerial");
            _stationIp = AppSetting.GetValue("StationSoftIP");

            string modemIp = AppSetting.GetValue("IpAddress");

            string modemUser = AppSetting.GetValue("UserName");
            string modemPwd = AppSetting.GetValue("Password");

            _commonObj = new Common(localIp, localPort, modemIp, modemUser, modemPwd);

            InitializeComponent();
        }

        private void WriteUint_Load(object sender, EventArgs e)
        {
            _commonObj.OnOutput += CommonObj_OnOutput;

            //if (_unitNumber == 3)//test
                Task.Run(() => Start());
        }

        private void CommonObj_OnOutput(string message)
        {
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message,ref _log);
        }


        private void Start()
        {
            while (true)
            {
                //wait for exited of optical modem
                WaitForModemExit();

                _log = string.Empty;

                Shared.SoftMethod.SoftShared.SetControl(this, this.textBoxMacAddr, string.Empty);
                Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "放入光猫");
                Shared.SoftMethod.SoftShared.SetControl(this, this.richTextBoxMsg, "10秒后，运行扫描\r\n");

                System.Threading.Thread.Sleep(10000);
                //get outside mac
                string outsideMac = Common.ScanSign(_serialPortName).Trim().ToUpper();

                //get inside mac
                if (string.IsNullOrEmpty(outsideMac)) continue;

                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, $"扫描MAC：{outsideMac}",ref _log);

                Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "获取光猫MAC", Color.BlueViolet);

                string insideMac = Common.GetModemMacFromArp(_commonObj.LocalIp, _commonObj.ModemIp).Trim().ToUpper();

                if (string.IsNullOrEmpty(insideMac)) continue;

                Shared.SoftMethod.SoftShared.SetControl(this, this.textBoxMacAddr, insideMac);

                string msg = string.Empty;

                //inspect can do this part
                bool canTest = StationTest.IfCanTest(insideMac, ref msg, _stationIp);

                if (canTest == false)
                {
                    Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, msg, ref _log);
                    continue;
                }

                //switch which way to go
                WORK_STEP step = Common.CheckStep(insideMac, outsideMac, out string message);

                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

                if (step == WORK_STEP.NO_WHERE) continue;

                bool workResult = false;

                //LOG_TYPE logType = LOG_TYPE.WRITE_TEST;
                bool writeSuccess = false;

                //write/testing step
                if (step == WORK_STEP.WRITE_MSG)
                {
                    if (RunWrite(insideMac, outsideMac, out YcdTelnetSecond tel, out ModemType modemTypeLocal))
                    {
                        if (ChangeToUserState(tel, modemTypeLocal))
                        {
                            workResult = RunInspectWeb(outsideMac);
                            //logType = LOG_TYPE.RESET_TO_USER;
                            writeSuccess = true;
                        }
                    }
                    else
                    {
                        //write inside mac, unbind, write factory model
                        ChangeToFactoryState(insideMac, outsideMac, tel);
                    }
                }
                //inspect web
                else
                {
                    workResult = RunInspectWeb(outsideMac);

                    writeSuccess = true;
                }

                //write log
                RunWriteLog(workResult, insideMac, outsideMac, writeSuccess);

                Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, workResult ? "PASS" : "FAIL", workResult ? Color.Green : Color.Red);
            }
        }

        private bool RunWrite(string insideMac, string outsideMac, out YcdTelnetSecond tel, out ModemType modemTypeLocal)
        {
            //binding
            tel = null;
            modemTypeLocal = ModemType.DEFAULT;

            bool bindResult = Common.BindingMac(insideMac, outsideMac, out Device_Data deviceData, out string message);

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            if (bindResult == false || deviceData == null)
            {
                return false;
            }
            //get device data item
            var deviceType = Common.GetDeviceType(deviceData.DeviceType, deviceData.HW_PROVINCE_NAME);

            if (deviceType == null)
            {
                return false;
            }
            //get telnet object
            tel = _commonObj.GetTelnetSecond();

            if (tel == null)
            {
                return false;
            }

            //writting messages
            if (_commonObj.CheckInformation(deviceData, deviceType, tel, out modemTypeLocal) == false) return false;

            if (_commonObj.WriteInformation(deviceData, deviceType, tel) == false) return false;

            if (_commonObj.WriteInformationSpecial(deviceData, deviceType, tel, modemTypeLocal) == false) return false;

            //testing functions
            if (RunButtonVoiceTest(tel, modemTypeLocal) == false) return false;

            //scan outside mac, inspect two scan
            string scanMac = Common.ScanSign(_serialPortName);

            if (scanMac != outsideMac) return false;

            //write mac and province
            return _commonObj.WriteMacProvince(deviceData, tel);
        }

        private bool ChangeToUserState(YcdTelnetSecond tel, ModemType modemTypeLocal)
        {
            var taskResult = Common.ResetModem(tel, modemTypeLocal, out string message);

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message);

            //close and open power
            if (taskResult)
                Common.PowerOffAndOn(_unitNumber, _serialPowerName);

            return taskResult;
        }

        private void ChangeToFactoryState(string insideMac, string outsideMac, YcdTelnetSecond tel)
        {
            if (tel == null || tel.Connected == false) return;

            //write inside mac
            tel.SendAndRecv($"flash set ELAN_MAC_ADDR {insideMac}", $"={insideMac}", out string message);
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            //write factory modem
            tel.SendAndRecv("flash set HW_PROVINCE_NAME FACTORY", "=FACTORY",out message);
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            //unbind inside and outside mac
            var unbindRet = Common.Unbinding(outsideMac, insideMac);

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg,$"Unbinding ycdmac:{insideMac} and mac{outsideMac}, {unbindRet}");
        }


        private bool RunInspectWeb(string outsideMac)
        {
            //inspect scan mac and outside mac
            //string scanMac = Common.ScanSign(_serialPortName).Trim().ToUpper();

            //if (scanMac != outsideMac)
            //{
            //    Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "扫描的MAC与之前处理的MAC不一致",ref _log);
            //    return false;
            //}
            //ping optical modem

            string insideMac = Common.GetModemMacFromArp(_commonObj.LocalIp, _commonObj.ModemIp).Trim().ToUpper();

            if (insideMac != outsideMac)
            {
                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "内外MAC不一致",ref _log);
                return false;
            }

            bool inspectWeb= _commonObj.CheckWebMain(outsideMac, out string message, out string worning);

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            if (string.IsNullOrEmpty(worning) == false)
            {
                Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, worning,inspectWeb?Color.Green:Color.Red);
            }

            return inspectWeb;
        }

        private void RunWriteLog(bool result,string insideMac,string outsideMac,bool writeSuccess)
        {
            string message = string.Empty;

            if(StationTest.SaveTestData(insideMac, result, _log, ref message, _stationIp)==false)
            {
                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "写日志失败");
                //Shared.SoftMethod.SoftShared.SetControl(this, this.labelResultOne, "写日志失败", Color.Red);
            }

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message);

            if (writeSuccess)
            {
                Common.InsertPartFinishProcess(outsideMac, writeSuccess, WORK_STEP.WRITE_MSG);
            }
        }

        private void WaitForModemExit()
        {
            //判断光猫断开连接
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "断开光猫");

            while (PingBaseClass.PingTest(_commonObj.LocalIp, _commonObj.ModemIp) == true) System.Threading.Thread.Sleep(2000);
        }

        private bool RunButtonVoiceTest(YcdTelnetSecond tel, ModemType modemTypeLocal)
        {
            //USB测试
            Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "USB测试");
            bool usbTestResult = Common.UsbTest(tel, out string message);

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            if (usbTestResult == false)
            {
                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "USB测试失败");

                return false;
            }
            else
            {
                Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "USB测试成功", Color.BlueViolet);
            }

            string keywifi = string.Empty, keyreset = string.Empty;

            //string message;
            bool ret = false;

            if (modemTypeLocal == ModemType.YD_924)//移动
            {
                tel.SendAndRecv("killall -9 lanNetInfo", "#", out message);

                ret = tel.SendAndRecv("cat /proc/kmsg & led test start", "#", out message);
                keywifi = "wifi button";
                keyreset = "reset button";
            }
            else if (modemTypeLocal == ModemType.LT_952)//联通
            {
                ret = tel.SendAndRecv("cat /proc/kmsg & led test start", "#", out message);
                keywifi = "wifi button";
                keyreset = "reset button";
            }
            else if (modemTypeLocal == ModemType.DX_926)//电信9603C
            {
                ret = tel.SendAndRecv("cat /proc/kmsg &\r\n", "#", out message);
                keywifi = "wifi button";
                keyreset = "reset button";
            }
            else if (modemTypeLocal == ModemType.DX_101)//电信9603C ITV
            {
                ret = tel.SendAndRecv("cat /proc/kmsg & led test start\r\n", "#", out message);

                keywifi = "wifi button";
                keyreset = "led button";
            }
            else if (modemTypeLocal == ModemType.DX_924)
            {
                ret = tel.SendAndRecv("cat /proc/kmsg & led test start", "#", out message);
                keywifi = "<4>wifi";
                keyreset = "do nothing";
            }
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message);

            string keyVoice = "VpInitLine";

            //确认灯光正常

            if (ret == false)
            {
                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg,"未能开启按键测试功能",ref _log);
                return false;
            }

            Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "按WIFI键",Color.BlueViolet);
            if (Common.ButtonTesting(tel, keywifi,out message) == false) return false;
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "按复位按钮", Color.BlueViolet);
            if (Common.ButtonTesting(tel, keyreset,out message) == false) return false;
            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message, ref _log);

            Shared.SoftMethod.SoftShared.SetControl(this, this.labelTestResult, "语音测试",Color.BlueViolet);
            //语音测试
            bool voiceTestResult = Common.VoiceTesting(_unitNumber-1, tel, keyVoice,out message);

            Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, message);

            if (voiceTestResult == false)
            {
                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "语音测试失败", ref _log); 
                return false;
            }
            else
            {
                Shared.SoftMethod.SoftShared.AppendText(this, this.richTextBoxMsg, "语音测试成功", ref _log);
            }

            return true;
        }

        private void RichTextBoxMsg_TextChanged(object sender, EventArgs e)
        {

            richTextBoxMsg.SelectionStart = richTextBoxMsg.Text.Length;
            richTextBoxMsg.ScrollToCaret();
        }
    }
}
